package com.cwt_taxi_xa.util;

import android.content.Intent;
import android.content.res.AssetManager;

import com.cwt_taxi_xa.MainApplication;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import android_serialport_api.SerialPort;

/**
 * Created by ZQX on 2020/7/3 0003 15:12
 */
public class GPSUpdataUtil {








    SerialPort mSerialPort;
    InputStream ins;
    OutputStream outs;



    int length = 0;
    int bau = 9600;
    boolean read = false;
    String HW_name, HW_id, SW_name, SW_versions;






    private ArrayList<byte[]> upDataList;
    private int upListIndex = 0;





    private byte[] addCRLF(byte[] bytes) {
        byte[] data = new byte[bytes.length+2];
        System.arraycopy(bytes, 0, data, 0, bytes.length);
        data[data.length-2] = 0x0D;
        data[data.length-1] = 0x0A;
        return data;
    }

    private void sendData(int mid, byte[] data){
        byte[] order = getPackage(mid, data);
        sendData(order);
    }

    private void sendData(byte[] data){
        try{
            outs.write(data);
            AppLog.e("GPS报文-发送BUP数据:"+Tools.parseByte2HexStr(data));
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    boolean checking = false;
    public void check() {
        if(!checking){
            checking = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                       try{
                           Thread.sleep(300);
                           outs.write(addCRLF("$PCAS06,0*1B".getBytes()));
                           for (int i = 0; i < 5; i++) {
                               Thread.sleep(500);
                               if(SW_versions==null){
                                   outs.write(addCRLF("$PCAS06,0*1B".getBytes()));
                               }else{
                                   onGPS.onCheck(SW_versions);
                                   break;
                               }
                           }
                       }catch(Exception e){
                           e.printStackTrace();
                       }
                       checking = false;
                }
            }).start();
        }
    }

    private void close(){
        try{
            ins.close();
            outs.close();
            mSerialPort.close();
        }catch(Exception e){
            e.printStackTrace();
        }

        read = false;
    }


    private void initSP() {
        try {
            mSerialPort = new SerialPort(new File("/dev/ttyS5"), bau, 0);
            ins = mSerialPort.getInputStream();
            outs = mSerialPort.getOutputStream();
            AppLog.e("GPS升级测试-初始化成功");
            new ReadThread().start();
            onGPS.onInit();
//            upDate();
        } catch (Exception e) {
            AppLog.e("GPS升级测试-初始化失败");
            e.printStackTrace();
        }
    }

    public void restartAndclose() {
        AppLog.e("GPS关闭串口");
        sendData(getPackage(0x06, new byte[0]));
        close();
    }


    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            byte[] buffer = new byte[64];
            int size;
            read = true;
            while (read) {
                try {
                    if (ins == null)
                        continue;
                    size = ins.read(buffer);
                    if (size > 0) {
                        onDataReceived(buffer, size);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private byte[] buffer = new byte[1024];
    private int index = 0;
    private byte[] bf_bup = new byte[512];
    private int id_bup = 0;
    private byte db = (byte) 0xDB;
    private byte dc = (byte) 0xDC;
    private byte de = (byte) 0xDE;
    private byte cb = (byte) 0xCB;
    private byte cc = (byte) 0xCC;
    private byte ce = (byte) 0xCE;
    private void onDataReceived(byte[] data, int size) {

        for (int i = 0; i < size; i++) {

            if(index==1024) index = 0;
            buffer[index] = data[i];
            index++;


            if(data[i]==0x0A&&buffer[index-2]==0x0D){
                onOrder(buffer, index);
                index = 0;
            }


            if(data[i]==db){
                bf_bup[0] = data[i];
                id_bup = 1;
            }else if(id_bup>0){
                bf_bup[id_bup] = data[i];
                id_bup++;
                if(id_bup>=bf_bup.length) id_bup = 0;
            }
            if(data[i]==de&&id_bup>0){
                onOrderBUP(bf_bup, id_bup);
                id_bup = 0;
            }

        }

    }

    private void onOrderBUP(byte[] buffer, int index) {
        byte[] date = new byte[index];
        System.arraycopy(buffer, 0, date, 0, index);
        date = transition2(date);
        AppLog.e("GPS报文-接收BUP数据:"+ Tools.parseByte2HexStr2(date));
        String mid = Tools.parseByte2HexStr(Tools.byteTobyte(date, 4, 1));
        String data_str = Tools.parseByte2HexStr(Tools.byteTobyte(date, 5, date.length-7));
        AppLog.e("GPS升级测试-接收BUP数据-解析:   mid:"+mid+"   data:"+data_str);

//        if(mid.equals("01")&&data_str.endsWith("00")){
//
//            AppLog.e("GPS升级测试-断开串口1");
//            read = false;
//            try {
//                outs.close();
//                ins.close();
//                mSerialPort.close();
//                AppLog.e("GPS升级测试-断开串口2");
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            bau = 115200;
//            AppLog.e("GPS升级测试-断开串口3");
//            handler.sendEmptyMessageDelayed(1005, 200);
//        }

        if(mid.equals("02")&&data_str.endsWith("00")){
            try {
//                sendData(upDataList.get(0));
//                upListIndex = 1;


                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int lastSend = -1;
                        try{
                            for (int i = 0; i < upDataList.size(); i++) {
                                if(lastSend==-1){
                                    AppLog.e("GPS升级测试-升级包:  size:"+upDataList.size()+"  index:"+0);
                                    sendData(upDataList.get(0));
                                    upListIndex = 0;
                                    lastSend = 0;
                                }else{
                                    for (int i1 = 0; i1 < 35; i1++) {
                                        Thread.sleep(100);
                                        if(upListIndex<=lastSend){
                                            if(i1==10||i1==20||i1==30){
                                                AppLog.e("GPS升级测试-升级包:  size:"+upDataList.size()+"  index:"+lastSend);
                                                sendData(upDataList.get(lastSend));
                                            }
                                        }else{
                                            break;
                                        }
                                    }
                                    if(upListIndex<=lastSend){
                                        break;
                                    }
                                    lastSend++;
                                    AppLog.e("GPS升级测试-升级包:  size:"+upDataList.size()+"  index:"+lastSend);
                                    onGPS.onUpdata(100*lastSend/upDataList.size());
                                    sendData(upDataList.get(lastSend));
                                }
                            }
                        }catch(Exception e){
                            e.printStackTrace();
                        }
                    }
                }).start();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if(mid.equals("05")&&(data_str.endsWith("00")||data_str.endsWith("02"))){
            upListIndex = Integer.parseInt(Tools.parseByte2HexStr(Tools.byteTobyte(date, 5, 1)), 16)
                    +Integer.parseInt(Tools.parseByte2HexStr(Tools.byteTobyte(date, 6, 1)), 16)*256;
            AppLog.e("GPS升级测试-upListIndex:"+upListIndex);
//            try {
//                if(upListIndex<upDataList.size()){
//                    sendData(upDataList.get(upListIndex));
////                    upListIndex++;
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
        }

        if(mid.equals("86")&&data_str.endsWith("00")){
            onGPS.onSucceed();
            sendData(getPackage(0x06, new byte[0]));


            try {
                Intent intent = new Intent(
                        "android.intent.action.ACTION_REQUEST_SHUTDOWN");
                intent.putExtra("android.intent.extra.KEY_CONFIRM", false);
                // 其中false换成true,会弹出是否关机的确认窗口
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                MainApplication.getInstance().startActivity(intent);

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }


    }




    byte[] od1 = "$GPTXT".getBytes();
    byte[] od2 = "$PCAS30".getBytes();
    private void onOrder(byte[] date, int size){

        if(test(od1, date)||test(od2, date)){
            byte[] result = new byte[size];
            System.arraycopy(date, 0, result, 0, size);
            String str = new String(result);
//            AppLog.e("GPS升级测试-模块数据:"+str);

            try{
                if(str.startsWith("$GPTXT,01,01,02,HW=")){
                    HW_name = str.substring(str.indexOf("HW=")+3, str.lastIndexOf(","));
                    HW_id = str.substring(str.lastIndexOf(",")+1, str.lastIndexOf("*"));
                    AppLog.e("GPS升级测试-模块型号:"+HW_name);
                    AppLog.e("GPS升级测试-模块编号:"+HW_id);
                }

                else if(str.startsWith("$GPTXT,01,01,02,SW=")){
                    SW_name = str.substring(str.indexOf("SW=")+3, str.lastIndexOf(","));
                    SW_versions = str.substring(str.lastIndexOf(",")+1, str.lastIndexOf("*"));
                    AppLog.e("GPS升级测试-软件代号:"+SW_name);
                    AppLog.e("GPS升级测试-软件版本:"+SW_versions);
                }

                else if(str.startsWith("$PCAS30,3*1D")){
                    AppLog.e("GPS升级测试-启动升级");
                    byte[] data = new byte[10];
                    int count = 0;
                    System.arraycopy(Tools.int2Bytes(1, 2), 0, data, count, 2);
                    count+=2;
                    System.arraycopy(Tools.int2Bytes(length, 4), 0, data, count, 4);
                    count+=4;
                    System.arraycopy(Tools.int2Bytes(0, 4), 0, data, count, 4);
                    count+=4;
                    sendData(0x02, data);
                }
            }catch(Exception e){
                e.printStackTrace();
            }

        }

    }







    public void upDate(){
        try {


            AssetManager assetManager = MainApplication.topActivity.getAssets();
            InputStream asis = assetManager.open("GPS53");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int busize = 0;
            while ((busize = asis.read(buffer)) != -1) {
                baos.write(buffer, 0, busize);
            }
            byte[] date = baos.toByteArray();
            baos.close();
            AppLog.e("文件长度："+date.length);
            date = Tools.byteTobyte(date, 256, date.length-256-4);
            AppLog.e("固件长度："+date.length);
            length = date.length;


            int unit = 512;

            int pksize = date.length/unit;
            if (date.length%unit!=0) pksize++;

            upDataList = new ArrayList<>();

            for (int i = 0; i < pksize-1; i++) {
                byte[] ud = new byte[unit+6];
                System.arraycopy(Tools.int2Bytes(pksize, 2), 0, ud, 0, 2);
                System.arraycopy(Tools.int2Bytes(i+1, 2), 0, ud, 2, 2);
                System.arraycopy(Tools.int2Bytes(unit, 2), 0, ud, 4, 2);
                System.arraycopy(date, unit*i, ud, 6, unit);
                upDataList.add(getPackage(0x05, ud));
            }
            if (date.length%unit!=0){
                int size = date.length%unit;
                byte[] ud = new byte[size+6];
                System.arraycopy(Tools.int2Bytes(pksize, 2), 0, ud, 0, 2);
                System.arraycopy(Tools.int2Bytes(pksize, 2), 0, ud, 2, 2);
                System.arraycopy(Tools.int2Bytes(size, 2), 0, ud, 4, 2);
                System.arraycopy(date, unit*(pksize-1), ud, 6, size);
                upDataList.add(getPackage(0x05, ud));
            }

            AppLog.e("分包长度："+upDataList.size());


            outs.write(addCRLF("$PCAS20*03".getBytes()));


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

















////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    private byte[] getPackage(int mid, byte[] data){
        byte[] p = new byte[data.length+7];
        int count = 0;
        p[count] = (byte) 0xdb;
        count++;
        System.arraycopy(Tools.int2Bytes(data.length+3, 2), 0, p, count, 2);
        count+=2;
        p[count] = (byte) 0x01;
        count++;
        p[count] = (byte) mid;
        count++;
        System.arraycopy(data, 0, p, 5, data.length);
        count+=data.length;
        p[count] = (byte) getXor(p, 1, p.length-2);
        count++;
        p[count] = (byte) 0xde;
        byte[] result = transition(p);
//        AppLog.e("GPS升级测试-getPackage:"+Tools.parseByte2HexStr2(result));
        return result;
//        return transition(p);
    }

    private byte[] transition(byte[] p) {

        int count = 0;
        for (int i = 1; i < p.length-1; i++) {
            if(p[i]==db||p[i]==dc||p[i]==de){
                count++;
            }
        }

        if(count==0){
            return p;
        }

//        AppLog.e("GPS升级测试-转义-count:"+count);

        byte[] result = new byte[p.length+count];
        result[0] = db;
        int index = 1;
        for (int i = 1; i < p.length-1; i++) {
            if(p[i]==db){
                result[index] = dc;
                result[index+1] = cb;
                index+=2;
            }else if(p[i]==dc){
                result[index] = dc;
                result[index+1] = cc;
                index+=2;
            }else if(p[i]==de){
                result[index] = dc;
                result[index+1] = ce;
                index+=2;
            }else{
                result[index] = p[i];
                index++;
            }
        }
        result[index] = de;
        return result;
//        index++;
//        byte[] enddate = new byte[index];
//        System.arraycopy(result, 0, enddate, 0, index);
//        return enddate;
    }

    private byte[] transition2(byte[] p) {

        int count = 0;
        for (int i = 1; i < p.length-1; i++) {
            if(p[i]==dc){
                count++;
            }
        }
        if(count==0){
            return p;
        }

//        AppLog.e("GPS升级测试-逆转义-count:"+count);

        byte[] result = new byte[p.length-count];
        result[0] = db;
        int index = 1;
        for (int i = 1; i < p.length-1; i++) {
            if(p[i]==dc){
                if(p[i+1]==cb){
                    result[index] = db;
                }else if(p[i+1]==cc){
                    result[index] = dc;
                }else if(p[i+1]==ce){
                    result[index] = de;
                }
                i++;
            }else{
                result[index] = p[i];
            }
            index++;
        }
        result[index] = de;
        return result;
//        index++;
//        byte[] enddate = new byte[index];
//        System.arraycopy(result, 0, enddate, 0, index);
//        return enddate;
    }

    private byte getXor(byte[] p, int index, int end) {
        byte result = p[index];
        for (int i = index+1; i < end; i++) {
            result^=p[i];
        }
        return result;
    }

    private boolean test(byte[] od, byte[] date){
        boolean path = true;
        for (int i = 0; i < od.length; i++) {
            if(date[i] != od[i]){
                path = false;
            }
        }
        return path;
    }


    private onGPSUpdata onGPS;

    public interface onGPSUpdata{
        void onInit();
        void onUpdata(int percent);
        void onSucceed();
        void onCheck(String version);
        void onFailure();
    }

    public void initGpsUpdata(onGPSUpdata gps){
        onGPS = gps;
        initSP();
        new Thread(new Runnable() {
            @Override
            public void run() {
                   try{
                       for (int i = 0; i < 5 * 60; i++) {
                           if(read){
                               if(i==5*60-1){
                                   onGPS.onFailure();
                               }
                               Thread.sleep(1000);
                           }else{
                               break;
                           }
                       }
                   }catch(Exception e){
                       e.printStackTrace();
                   }
            }
        }).start();
    }


}
